home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #1 / Amiga Plus CD - 2000 - No. 1.iso / Tools / Dev / mamesrc / src / amiga / audio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-03  |  30.2 KB  |  1,091 lines

  1. /**************************************************************************
  2.  *
  3.  * Copyright (C) 1999 Mats Eirik Hansen (mats.hansen@triumph.no)
  4.  *
  5.  * $Id: audio.c,v 1.1 1999/04/28 18:50:48 meh Exp $
  6.  *
  7.  * $Log: audio.c,v $
  8.  * Revision 1.1  1999/04/28 18:50:48  meh
  9.  * Initial revision
  10.  *
  11.  *
  12.  *************************************************************************/
  13.  
  14. #include <clib/alib_protos.h>
  15.  
  16. #include <exec/execbase.h>
  17. #include <exec/memory.h>
  18. #include <devices/ahi.h>
  19. #include <devices/audio.h>
  20.  
  21. #include <inline/exec.h>
  22. #include <inline/dos.h>
  23. #include <inline/utility.h>
  24. #define AHI_BASE_NAME audio->AHIBase
  25. #include <inline/ahi.h>
  26.  
  27. #ifdef POWERUP
  28. #include <powerup/ppclib/memory.h>
  29. #include <inline/ppc.h>
  30. #endif
  31.  
  32. #include "audio.h"
  33.  
  34. #define DEF_BUFFER_SIZE     32768
  35. #define DEF_MIN_FREE_CHIP   (64*1024)
  36.  
  37. #define MAX_AHI_CHANNEL_TAGS  9
  38. #define MAX_PAULA_FREQUENCY   28867
  39. #define MAX_PAULA_LENGTH    65536
  40.  
  41. #define MAKE_PERIOD(f) ((f)?(((ULONG)3579547)/f):(65536))
  42.  
  43. #define INTELULONG(i) (((i)<<24)|((i)>>24)|(((i)<<8)&0x00ff0000)|(((i)>>8)&0x0000ff00))
  44.  
  45. extern struct Library *SysBase;
  46. extern struct Library *DOSBase;
  47. extern struct Library *UtilityBase;
  48.  
  49. #ifdef POWERUP
  50. extern struct Library *PPCLibBase;
  51.  
  52. static inline APTR memAlloc(ULONG size)
  53. {
  54.   return(PPCAllocVec(size, MEMF_PUBLIC|MEMF_CLEAR));
  55. }
  56.  
  57. static inline void memFree(APTR mem)
  58. {
  59.   PPCFreeVec(mem);
  60. }
  61. #else
  62. static inline APTR memAlloc(ULONG size)
  63. {
  64.   return(AllocVec(size, MEMF_PUBLIC|MEMF_CLEAR));
  65. }
  66.  
  67. static inline void memFree(APTR mem)
  68. {
  69.   FreeVec(mem);
  70. }
  71. #endif
  72.  
  73. struct Audio *AllocAudio(Tag tags,...)
  74. {
  75.   struct Audio  *audio;
  76.   struct TagItem  *tag, *taglist;
  77.   LONG      use_ahi;
  78.   LONG      channels;
  79.   LONG      max_sounds;
  80.   LONG      buffer_size;
  81.   BYTE      map_channels[4];
  82.   ULONG     min_free_chip;
  83.   LONG      size;
  84.   LONG      i;
  85.  
  86.   taglist = (struct TagItem *) &tags;
  87.  
  88.   use_ahi     = FALSE;
  89.   channels    = 4;
  90.   max_sounds    = 0;
  91.   min_free_chip = DEF_MIN_FREE_CHIP;
  92.   buffer_size   = DEF_BUFFER_SIZE;
  93.   map_channels[0] = 0;
  94.   map_channels[1] = 1;
  95.   map_channels[2] = 2;
  96.   map_channels[3] = 3;
  97.  
  98.   while((tag = NextTagItem(&taglist)))
  99.   {
  100.     switch(tag->ti_Tag)
  101.     {
  102.       case AA_UseAHI:
  103.         use_ahi = tag->ti_Data;
  104.         break;
  105.       case AA_Channels:
  106.         channels = tag->ti_Data;
  107.         break;
  108.       case AA_MaxSounds:
  109.         max_sounds = tag->ti_Data;
  110.         break;
  111.       case AA_MapChannel0:
  112.         map_channels[0] = tag->ti_Data;
  113.         break;
  114.       case AA_MapChannel1:
  115.         map_channels[1] = tag->ti_Data;
  116.         break;
  117.       case AA_MapChannel2:
  118.         map_channels[2] = tag->ti_Data;
  119.         break;
  120.       case AA_MapChannel3:
  121.         map_channels[3] = tag->ti_Data;
  122.         break;
  123.       case AA_MinFreeChip:
  124.         min_free_chip = tag->ti_Data;
  125.         break;
  126.     }
  127.   }
  128.  
  129.   size = sizeof(struct Audio);
  130.   
  131.   if(use_ahi)
  132.     size += ((channels * MAX_AHI_CHANNEL_TAGS) + 1) * sizeof(struct TagItem);
  133.   else
  134.     size += 9 * sizeof(struct IOAudio);
  135.  
  136.   audio = AllocVec(size, MEMF_CLEAR|MEMF_PUBLIC);
  137.   
  138.   if(audio)
  139.   {
  140.     NewList((struct List *) &audio->Sounds);
  141.  
  142.     audio->UseAHI   = use_ahi;
  143.     audio->Channels   = channels;
  144.     audio->BufferSize = ((buffer_size + 3) >> 2) << 2;
  145.     audio->MasterVolume = 100;
  146.     audio->NextSound  = 1;
  147.     audio->MinFreeChip  = min_free_chip;
  148.  
  149.     for(i = 0; i < 4; i++)
  150.     {
  151.       if(map_channels[i] < channels)
  152.         audio->MapChannels[i] = map_channels[i];
  153.       else
  154.         audio->MapChannels[i] = i;
  155.     }
  156.  
  157.     audio->ChannelArray = AAllocChannelArray(audio, 0);
  158.  
  159.     if(audio->ChannelArray)
  160.     {
  161.       audio->MsgPort  = CreateMsgPort();
  162.         
  163.       if(audio->MsgPort)
  164.       {
  165.         if(use_ahi)
  166.         {
  167.           audio->AHITags    = (struct TagItem *) &audio[1];
  168.           audio->AHIRequest = (struct AHIRequest *) CreateIORequest(audio->MsgPort, sizeof(struct AHIRequest));
  169.           
  170.           if(audio->AHIRequest)
  171.           {
  172.             audio->AHIRequest->ahir_Version = 4;
  173.           
  174.             if(!OpenDevice(AHINAME, AHI_NO_UNIT, (struct IORequest *) audio->AHIRequest, 0))
  175.             {
  176.               audio->AHIBase  = (struct Library *) audio->AHIRequest->ahir_Std.io_Device;
  177.  
  178.               audio->AHIAudioCtrl = AHI_AllocAudio( AHIA_Channels,  channels,
  179.                                   AHIA_Sounds,  max_sounds + 1,
  180.                                   TAG_END);
  181.                                   
  182.               if(audio->AHIAudioCtrl)
  183.               {
  184.                 audio->AHISampleInfo.ahisi_Type   = AHIST_M8S;
  185.                 audio->AHISampleInfo.ahisi_Address  = 0;
  186.                 audio->AHISampleInfo.ahisi_Length = 0xffffffff;
  187.               
  188.                 if(!AHI_LoadSound(0, AHIST_DYNAMICSAMPLE, &audio->AHISampleInfo, audio->AHIAudioCtrl))
  189.                 {
  190.                   AHI_ControlAudio(audio->AHIAudioCtrl, AHIC_Play, TRUE);
  191.  
  192.                   audio->AHIEffMasterVolume.ahie_Effect = AHIET_MASTERVOLUME;
  193.                   audio->AHIEffMasterVolume.ahiemv_Volume = (audio->Channels >> 1) * 0x10000;
  194.       
  195.                   AHI_SetEffect(&audio->AHIEffMasterVolume, audio->AHIAudioCtrl);
  196.  
  197.                   return(audio);
  198.                 }
  199.  
  200.                 AHI_FreeAudio(audio->AHIAudioCtrl);
  201.               }
  202.               
  203.               CloseDevice((struct IORequest *) audio->AHIRequest);
  204.             }
  205.             
  206.             DeleteIORequest((struct IORequest *) audio->AHIRequest);
  207.           }
  208.         }
  209.         else
  210.         {
  211.           UBYTE ch;
  212.  
  213.           audio->AudioRequests = (struct IOAudio *) &audio[1];
  214.           
  215.           for(i = 0; i < 9; i++)
  216.           {
  217.             audio->AudioRequests[i].ioa_Request.io_Message.mn_ReplyPort = audio->MsgPort;
  218.             audio->AudioRequests[i].ioa_Request.io_Message.mn_Length  = sizeof(struct IOAudio);
  219.           }
  220.           
  221.           audio->Buffers = AllocVec(8 * audio->BufferSize, MEMF_PUBLIC|MEMF_CHIP);
  222.           
  223.           if(audio->Buffers)
  224.           {
  225.             ch = 0xf;
  226.           
  227.             audio->AudioRequests[0].ioa_Request.io_Command  = ADCMD_ALLOCATE;
  228.             audio->AudioRequests[0].ioa_Request.io_Flags  = ADIOF_NOWAIT|IOF_QUICK;
  229.             audio->AudioRequests[0].ioa_Data        = &ch;
  230.             audio->AudioRequests[0].ioa_Length        = 1;
  231.  
  232.             if(!OpenDevice("audio.device", 0, (struct IORequest *) audio->AudioRequests, 0))
  233.             {
  234.               for(i = 1; i < 9; i++)
  235.               {
  236.                 audio->AudioRequests[i].ioa_Request.io_Device = audio->AudioRequests->ioa_Request.io_Device;
  237.                 audio->AudioRequests[i].ioa_AllocKey      = audio->AudioRequests->ioa_AllocKey;
  238.               }
  239.  
  240.               return(audio);
  241.             }
  242.             
  243.             FreeVec(audio->Buffers);
  244.           }
  245.         }
  246.  
  247.         DeleteMsgPort(audio->MsgPort);
  248.       }
  249.       
  250.       AFreeChannelArray(audio->ChannelArray);
  251.     }
  252.     
  253.     FreeVec(audio);
  254.   }
  255.   
  256.   return(NULL);
  257. }
  258.  
  259. void FreeAudio(struct Audio *audio)
  260. {
  261.   struct MinNode  *node;
  262.   struct IOAudio  *ioa;
  263.   LONG      i;
  264.  
  265.   node = audio->Sounds.mlh_Head->mln_Succ;
  266.  
  267.   while(node)
  268.   {
  269.     if(audio->UseAHI)
  270.       AHI_UnloadSound(((struct ASound *) node->mln_Pred)->Sound, audio->AHIAudioCtrl);
  271.     else if(((struct ASound *) node->mln_Pred)->AHISampleInfo.ahisi_Address != &((struct ASound *) node->mln_Pred)[1])
  272.       FreeVec(((struct ASound *) node->mln_Pred)->AHISampleInfo.ahisi_Address);
  273.  
  274.     memFree(node->mln_Pred);
  275.     
  276.     node = node->mln_Succ;
  277.   }
  278.  
  279.   if(audio->UseAHI)
  280.   {
  281.     AHI_UnloadSound(0, audio->AHIAudioCtrl);
  282.     AHI_FreeAudio(audio->AHIAudioCtrl);
  283.     CloseDevice((struct IORequest *) audio->AHIRequest);
  284.     DeleteIORequest((struct IORequest *) audio->AHIRequest);
  285.     DeleteMsgPort(audio->MsgPort);
  286.   }
  287.   else
  288.   {
  289.     for(i = 0; i < 4; i++)
  290.     {
  291.       if(audio->Status[i] == AS_PLAYING1)
  292.         AbortIO((struct IORequest *) &audio->AudioRequests[2*i]);
  293.       else if(audio->Status[i] == AS_PLAYING2)
  294.         AbortIO((struct IORequest *) &audio->AudioRequests[2*i+1]);
  295.     }
  296.  
  297.     while(audio->Status[0] || audio->Status[1] || audio->Status[2] || audio->Status[3])
  298.     {
  299.       WaitPort(audio->MsgPort);
  300.  
  301.       ioa = (struct IOAudio *) GetMsg(audio->MsgPort);
  302.       
  303.       if(ioa)
  304.         audio->Status[(((ULONG) ioa) - ((ULONG) audio->AudioRequests)) / (sizeof(struct IOAudio) << 1)] = AS_IDLE;
  305.     }
  306.     
  307.     CloseDevice((struct IORequest *) audio->AudioRequests);
  308.     
  309.     FreeVec(audio->Buffers);
  310.   }
  311.  
  312.   AFreeChannelArray(audio->ChannelArray);
  313.  
  314.   FreeVec(audio);
  315. }
  316.  
  317. struct AChannelArray *AAllocChannelArray(struct Audio *audio, LONG length)
  318. {
  319.   struct AChannelArray  *ca;
  320.   LONG          size;
  321.   LONG          i;
  322.   BYTE          *buffer;
  323.   
  324.   size = sizeof(struct AChannelArray) + (audio->Channels * (sizeof(struct AChannel) + length));
  325.   
  326.   ca = (struct AChannelArray *) memAlloc(size);
  327.   
  328.   if(ca)
  329.   {
  330.     ca->Audio   = audio;
  331.     ca->Size    = size;
  332.     ca->Length    = length;
  333.     ca->Channels  = (struct AChannel *) &ca[1];
  334.     
  335.     buffer = (BYTE *) & ca->Channels[audio->Channels];
  336.     
  337.     for(i = 0; i < audio->Channels; i++)
  338.     {
  339.       ca->Channels[i].Buffer = buffer;
  340.       
  341.       buffer += length;
  342.     }
  343.  
  344. #ifdef POWERUP
  345.     PPCCacheClearE(ca, ca->Size, CACRF_ClearD);
  346. #endif
  347.   }
  348.   
  349.   return(ca);
  350. }
  351.  
  352. void AFreeChannelArray(struct AChannelArray *ca)
  353. {
  354.   if(ca)
  355.     memFree(ca);
  356. }
  357.  
  358. void ASetChannelFrame(struct AChannelArray *ca)
  359. {
  360.   struct Audio    *audio;
  361.   struct AChannel   *c;
  362.   struct AChannel   *ac;
  363.   struct ASound   *sound;
  364.   struct TagItem    *tags;
  365.   struct IOAudio    *aio;
  366.   LONG        i, j, k, l, o;
  367.   BYTE        stop_status[4];
  368.   BYTE        start_status[4];
  369.   BYTE        *sample;
  370.   BYTE        *buffer;
  371.   ULONG       length;
  372.   ULONG       len;
  373.   ULONG       freq;
  374.   ULONG       vol;
  375.   ULONG       step;
  376.  
  377.   audio = ca->Audio;
  378.   c   = ca->Channels;
  379.   ac    = audio->ChannelArray->Channels;
  380.   
  381.   if(audio->UseAHI)
  382.   {
  383.     tags  = audio->AHITags;
  384.     sound = NULL;
  385.  
  386.     for(i = 0, j = 0; i < audio->Channels; i++)
  387.     {
  388.       if(c[i].Flags)
  389.       {
  390.         if(c[i].Flags & ACF_Stop)
  391.           AHI_SetSound(i, AHI_NOSOUND, 0, 0, audio->AHIAudioCtrl, AHISF_IMM);
  392.         else if(c[i].Flags & ACF_Restart)
  393.         {
  394.           if(ac[i].Flags)
  395.           {
  396.             tags[j].ti_Tag    = AHIP_BeginChannel;
  397.             tags[j++].ti_Data = i;
  398.  
  399.             if(ac[i].Flags & ACF_SetSound)
  400.             {
  401.               k = ac[i].Sound;
  402.  
  403.               tags[j].ti_Tag    = AHIP_Sound;
  404.               tags[j++].ti_Data = k;
  405.               tags[j].ti_Tag    = AHIP_Pan;
  406.               if(i & 1)
  407.                 tags[j++].ti_Data = 0;
  408.               else
  409.                 tags[j++].ti_Data = 0x10000;
  410.           
  411.               sound = (struct ASound *) audio->Sounds.mlh_Head;
  412.  
  413.               while(--k)
  414.                 sound = (struct ASound *) sound->Node.mln_Succ;
  415.  
  416.               tags[j].ti_Tag    = AHIP_Offset;
  417.               tags[j++].ti_Data = 0;
  418.               tags[j].ti_Tag    = AHIP_Length;
  419.               tags[j++].ti_Data = sound->AHISampleInfo.ahisi_Length;
  420.             }
  421.             else if(ac[i].Flags & ACF_SetSample)
  422.             {
  423.               tags[j].ti_Tag    = AHIP_Sound;
  424.               tags[j++].ti_Data = 0;
  425.               tags[j].ti_Tag    = AHIP_Pan;
  426.               if(i & 1)
  427.                 tags[j++].ti_Data = 0;
  428.               else
  429.                 tags[j++].ti_Data = 0x10000;
  430.               tags[j].ti_Tag    = AHIP_Offset;
  431.               tags[j++].ti_Data = ac[i].Sound;
  432.             }
  433.             
  434.             tags[j].ti_Tag    = AHIP_Freq;
  435.             tags[j++].ti_Data = ac[i].Frequency;
  436.             tags[j].ti_Tag    = AHIP_Vol;
  437.             tags[j++].ti_Data = ac[i].Volume * 0x10000 / 100;
  438.             tags[j].ti_Tag    = AHIP_Length;
  439.             tags[j++].ti_Data = ac[i].Length;
  440.  
  441.             if(!(ac[i].Flags & ACF_Loop))
  442.             {
  443.               tags[j].ti_Tag    = AHIP_LoopSound;
  444.               tags[j++].ti_Data = AHI_NOSOUND;
  445.             }
  446.  
  447.             tags[j].ti_Tag    = AHIP_EndChannel;
  448.             tags[j++].ti_Data = NULL;
  449.           }
  450.         }
  451.         else
  452.         {   
  453.           tags[j].ti_Tag    = AHIP_BeginChannel;
  454.           tags[j++].ti_Data = i;
  455.  
  456.           if(c[i].Flags & ACF_SetSound)
  457.           {
  458.             k = c[i].Sound;
  459.  
  460.             tags[j].ti_Tag    = AHIP_Sound;
  461.             tags[j++].ti_Data = k;
  462.             tags[j].ti_Tag    = AHIP_Pan;
  463.             if(i & 1)
  464.               tags[j++].ti_Data = 0;
  465.             else
  466.               tags[j++].ti_Data = 0x10000;
  467.           
  468.             sound = (struct ASound *) audio->Sounds.mlh_Head;
  469.  
  470.             while(--k)
  471.               sound = (struct ASound *) sound->Node.mln_Succ;
  472.  
  473.             tags[j].ti_Tag    = AHIP_Offset;
  474.             tags[j++].ti_Data = 0;
  475.             tags[j].ti_Tag    = AHIP_Length;
  476.             tags[j++].ti_Data = sound->AHISampleInfo.ahisi_Length;
  477.  
  478.             ac[i].Flags = ACF_SetSound;
  479.             ac[i].Sound = c[i].Sound;
  480.  
  481.             if(c[i].Flags & ACF_Loop)
  482.               ac[i].Flags |= ACF_Loop;
  483.           }
  484.           else if(c[i].Flags & ACF_SetSample)
  485.           {
  486.             tags[j].ti_Tag    = AHIP_Sound;
  487.             tags[j++].ti_Data = 0;
  488.             tags[j].ti_Tag    = AHIP_Pan;
  489.             if(i & 1)
  490.               tags[j++].ti_Data = 0;
  491.             else
  492.               tags[j++].ti_Data = 0x10000;
  493.             tags[j].ti_Tag    = AHIP_Offset;
  494.             tags[j++].ti_Data = c[i].Sound;
  495.  
  496.             ac[i].Flags = ACF_SetSample;
  497.             ac[i].Sound = c[i].Sound;
  498.  
  499.             if(c[i].Flags & ACF_Loop)
  500.               ac[i].Flags |= ACF_Loop;
  501.           }
  502.  
  503.           if(c[i].Flags & ACF_SetFrequency)
  504.           {
  505.             tags[j].ti_Tag    = AHIP_Freq;
  506.             tags[j++].ti_Data = c[i].Frequency;
  507.             
  508.             ac[i].Frequency = c[i].Frequency;
  509.           }
  510.           else if(c[i].Flags & ACF_SetSound)
  511.           {
  512.             tags[j].ti_Tag    = AHIP_Freq;
  513.             tags[j++].ti_Data = sound->Frequency;
  514.  
  515.             ac[i].Frequency = sound->Frequency;
  516.           }
  517.  
  518.           if(c[i].Flags & ACF_SetVolume)
  519.           {
  520.             tags[j].ti_Tag    = AHIP_Vol;
  521.             tags[j++].ti_Data = c[i].Volume * 0x10000 / 100;
  522.  
  523.             ac[i].Volume  = c[i].Volume;
  524.           }
  525.           else if(c[i].Flags & ACF_SetSound)
  526.           {
  527.             tags[j].ti_Tag    = AHIP_Vol;
  528.             tags[j++].ti_Data = sound->Volume * 0x10000 / 100;
  529.  
  530.             ac[i].Volume  = sound->Volume;
  531.           }
  532.  
  533.           if(c[i].Flags & ACF_SetLength)
  534.           {
  535.             tags[j].ti_Tag    = AHIP_Length;
  536.             tags[j++].ti_Data = c[i].Length;
  537.  
  538.             ac[i].Length  = c[i].Length;
  539.           }
  540.  
  541.           if(!(c[i].Flags & ACF_Loop)
  542.           && ((c[i].Flags & ACF_SetSound) || (c[i].Flags & ACF_SetSample)))
  543.           {
  544.             tags[j].ti_Tag    = AHIP_LoopSound;
  545.             tags[j++].ti_Data = AHI_NOSOUND;
  546.           }
  547.  
  548.           tags[j].ti_Tag    = AHIP_EndChannel;
  549.           tags[j++].ti_Data = NULL;
  550.         }
  551.         
  552.         c[i].Flags = 0;
  553.       }
  554.  
  555.     }
  556.  
  557.     if((ca->Flags & ACF_SetVolume) && (ca->MasterVolume != audio->MasterVolume))
  558.     {
  559.       audio->AHIEffMasterVolume.ahiemv_Volume = (audio->Channels >> 1) * 0x10000 / 100 * ca->MasterVolume;
  560.  
  561.       AHI_SetEffect(&audio->AHIEffMasterVolume, audio->AHIAudioCtrl);
  562.       
  563.       audio->MasterVolume = ca->MasterVolume;
  564.     }
  565.  
  566.     ca->Flags = 0;
  567.  
  568.     if(j)
  569.     {
  570.       tags[j].ti_Tag = TAG_END;
  571.       
  572.       AHI_PlayA(audio->AHIAudioCtrl, audio->AHITags);
  573.     }
  574.   }
  575.   else
  576.   {
  577.     for(i = 0; i < 4; i++)
  578.     {
  579.       start_status[i] = AS_IDLE;
  580.       stop_status[i]  = AS_IDLE;
  581.     }
  582.  
  583.     if(ca->Flags & ACF_SetVolume)
  584.       vol = ca->MasterVolume;
  585.     else
  586.       vol = audio->MasterVolume;
  587.  
  588.     for(i = 0; i < audio->Channels; i++)
  589.     {
  590.       if(c[i].Flags)
  591.       {
  592.         for(j = 0; j < 4; j++)
  593.         {
  594.           if(audio->MapChannels[j] == i)
  595.           {
  596.             if((c[i].Flags & ACF_Stop) && audio->Status[j])
  597.             {
  598.               if(audio->Status[j] == AS_PLAYING1)
  599.                 AbortIO((struct IORequest *) &audio->AudioRequests[2*j]);
  600.               else if(audio->Status[j] == AS_PLAYING2)
  601.                 AbortIO((struct IORequest *) &audio->AudioRequests[2*j+1]);
  602.  
  603.               stop_status[j]    = audio->Status[j];
  604.               audio->Status[j]  = AS_IDLE;
  605.             }
  606.             else if(c[i].Flags & ACF_Restart)
  607.             {
  608.             }
  609.             else
  610.             {
  611.               if(c[i].Flags)
  612.               {
  613.                 if((c[i].Flags & ACF_SetSound) || (c[i].Flags & ACF_SetSample))
  614.                 {               
  615.                   if(c[i].Flags & ACF_SetSound)
  616.                   {
  617.                     k = c[i].Sound;
  618.  
  619.                     sound = (struct ASound *) audio->Sounds.mlh_Head;
  620.  
  621.                     while(--k)
  622.                       sound = (struct ASound *) sound->Node.mln_Succ;
  623.                   
  624.                     sample  = sound->AHISampleInfo.ahisi_Address;
  625.                     length  = sound->AHISampleInfo.ahisi_Length;
  626.                   }
  627.                   else
  628.                   {
  629.                     sample  = (BYTE *) c[i].Sound;
  630.                     length  = c[i].Length;
  631.                   }
  632.                   
  633.                   freq = c[i].Frequency;
  634.                   
  635.                   if(audio->Status[j] == AS_PLAYING1)
  636.                   {
  637.                     o = 1;
  638.                     start_status[j] = AS_PLAYING2;
  639.                     stop_status[j]  = AS_PLAYING1;
  640.                   }
  641.                   else
  642.                   {
  643.                     o = 0;
  644.                     start_status[j] = AS_PLAYING1;
  645.                     if(audio->Status[j] == AS_PLAYING2)
  646.                       stop_status[j]  = AS_PLAYING2;
  647.                   }
  648.  
  649.                   if((freq > MAX_PAULA_FREQUENCY) || (length > audio->BufferSize)
  650.                   || !(TypeOfMem(sample) & MEMF_CHIP))
  651.                   {
  652.                     len   = length;
  653.                     buffer  = audio->Buffers + (audio->BufferSize * ((j << 1) + o));
  654.                     step  = AResample(&freq, MAX_PAULA_FREQUENCY, &length, audio->BufferSize);
  655.                     
  656.                     if(step == 0x100)
  657.                     {
  658.                       len = (len + 3) >> 2;
  659.                       for(k = 0; k < len; k++)
  660.                         ((ULONG *) buffer)[k] = ((ULONG *) sample)[k];
  661.                     }
  662.                     else
  663.                     {
  664.                       for(k = 0, l = 0; k < length; k++, l += step)
  665.                         buffer[k] = sample[l >> 8];
  666.                     }
  667.                     
  668.                     sample = buffer;
  669.                   }
  670.  
  671.                   length &= 0xfffffffe;
  672.  
  673.                   audio->AudioRequests[2*j+o].ioa_Request.io_Unit   = (struct Unit *) (1<<j);
  674.                   audio->AudioRequests[2*j+o].ioa_Request.io_Command  = CMD_WRITE;
  675.                   audio->AudioRequests[2*j+o].ioa_Request.io_Flags  = ADIOF_PERVOL;
  676.                   audio->AudioRequests[2*j+o].ioa_Data        = sample;
  677.                   audio->AudioRequests[2*j+o].ioa_Length        = length;
  678.                   audio->AudioRequests[2*j+o].ioa_Period        = MAKE_PERIOD(freq);
  679.                   audio->AudioRequests[2*j+o].ioa_Volume        = (64 * vol * c[i].Volume) / 10000;
  680.                   audio->AudioRequests[2*j+o].ioa_Cycles        = (c[i].Flags & ACF_Loop) ? 0 : 1;
  681.                   
  682.                   ac[i].Frequency = freq;
  683.                   ac[i].Volume  = c[i].Volume;
  684.                   ac[i].Length  = length;
  685.                   ac[i].Sound   = (LONG) sample;
  686.                   
  687.                   audio->FrequencyModifier[j] = (freq << 12) / c[i].Frequency;
  688.                 }
  689.                 else if(audio->Status[j])
  690.                 {
  691.                   if(audio->Status[j] == AS_PLAYING1)
  692.                   {
  693.                     o = 1;
  694.                     start_status[j] = AS_PLAYING2;
  695.                     stop_status[j]  = AS_PLAYING2;
  696.                   }
  697.                   else
  698.                   {
  699.                     o = 0;
  700.                     start_status[j] = AS_PLAYING1;
  701.                     stop_status[j]  = AS_PLAYING1;
  702.                   }
  703.  
  704.                   if(c[i].Flags & ACF_SetFrequency)
  705.                     ac[i].Frequency = (audio->FrequencyModifier[j] * c[i].Frequency) >> 12;
  706.  
  707.                   if(c[i].Flags & ACF_SetVolume)
  708.                     ac[i].Volume = c[i].Volume;
  709.                   
  710.                   audio->AudioRequests[2*j+o].ioa_Request.io_Unit   = (struct Unit *) (1<<j);
  711.                   audio->AudioRequests[2*j+o].ioa_Request.io_Command  = ADCMD_PERVOL;
  712.                   audio->AudioRequests[2*j+o].ioa_Request.io_Flags  = 0;
  713.                   audio->AudioRequests[2*j+o].ioa_Period        = MAKE_PERIOD(ac[i].Frequency);
  714.                   audio->AudioRequests[2*j+o].ioa_Volume        = (64 * vol * ac[i].Volume) / 10000;
  715.                 }
  716.               }
  717.             }
  718.           }
  719.         }
  720.       }
  721.     }
  722.  
  723.     for(j = 0; j < 4; j++)
  724.     {
  725.       if(start_status[j] == AS_PLAYING1)
  726.       {
  727.         BeginIO((struct IORequest *) &audio->AudioRequests[2*j]);
  728.  
  729.         if(audio->Status[j] == AS_PLAYING2)
  730.           AbortIO((struct IORequest *) &audio->AudioRequests[2*j+1]);
  731.       }
  732.       else if(start_status[j] == AS_PLAYING2)
  733.       {
  734.         BeginIO((struct IORequest *) &audio->AudioRequests[2*j+1]);
  735.  
  736.         if(audio->Status[j] == AS_PLAYING1)
  737.           AbortIO((struct IORequest *) &audio->AudioRequests[2*j]);
  738.       }
  739.     }
  740.  
  741.     while(stop_status[0] || stop_status[1] || stop_status[2] || stop_status[3])
  742.     {
  743.       WaitPort(audio->MsgPort);
  744.       
  745.       while((aio = (struct IOAudio *) GetMsg(audio->MsgPort)))
  746.       {
  747.         i = (((ULONG) aio) - ((ULONG) audio->AudioRequests)) / sizeof(struct IOAudio);
  748.  
  749.         if(i&1)
  750.         {
  751.           if(stop_status[i>>1] == AS_PLAYING2)
  752.           {
  753.             audio->Status[i>>1] = AS_IDLE;
  754.             stop_status[i>>1] = AS_IDLE;
  755.           }
  756.           else
  757.             start_status[i>>1] = AS_IDLE;
  758.         }
  759.         else
  760.         {
  761.           if(stop_status[i>>1] == AS_PLAYING1)
  762.           {
  763.             audio->Status[i>>1] = AS_IDLE;
  764.             stop_status[i>>1] = AS_IDLE;
  765.           }
  766.           else
  767.             start_status[i>>1] = AS_IDLE;
  768.         }
  769.       }
  770.     }
  771.  
  772.     if(vol != audio->MasterVolume)
  773.     {
  774.       audio->MasterVolume = vol;
  775.       
  776.       for(j = 0; j < 4; j++)
  777.       {
  778.         if(audio->Status[j] && !start_status[j])
  779.         {
  780.           if(audio->Status[j] == AS_PLAYING1)
  781.             o = 1;
  782.           else
  783.             o = 0;
  784.                   
  785.           audio->AudioRequests[2*j+o].ioa_Request.io_Unit   = (struct Unit *) (1<<j);
  786.           audio->AudioRequests[2*j+o].ioa_Request.io_Command  = ADCMD_PERVOL;
  787.           audio->AudioRequests[2*j+o].ioa_Request.io_Flags  = 0;
  788.           audio->AudioRequests[2*j+o].ioa_Period        = MAKE_PERIOD(ac[i].Frequency);
  789.           audio->AudioRequests[2*j+o].ioa_Volume        = (64 * vol * ac[i].Volume) / 10000;
  790.  
  791.           DoIO((struct IORequest *) &audio->AudioRequests[2*j+o]);
  792.         }
  793.       }
  794.     }   
  795.  
  796.     for(j = 0; j < 4; j++)
  797.     {
  798.       if(start_status[j])
  799.         audio->Status[j] = start_status[j];
  800.     }
  801.   }
  802. }
  803.  
  804. struct ASound *ALoadSound(struct Audio *audio, UBYTE *sample, LONG res, LONG length, LONG freq, LONG vol)
  805. {
  806.   struct ASound *sound;
  807.   UBYTE     *buffer;
  808.   LONG      step;
  809.   LONG      i, j;
  810.  
  811.   if(audio->UseAHI)
  812.   {
  813.     sound = memAlloc(sizeof(struct ASound) + length);
  814.         
  815.     if(sound)
  816.     {
  817.       sound->Sound    = audio->NextSound;
  818.       sound->Frequency  = freq;
  819.       sound->Volume   = vol;
  820.           
  821.       memcpy(&sound[1], sample, length);
  822.           
  823.       if(res == 8)
  824.         sound->AHISampleInfo.ahisi_Type = AHIST_M8S;
  825.       else
  826.         sound->AHISampleInfo.ahisi_Type = AHIST_M16S;
  827.           
  828.       sound->AHISampleInfo.ahisi_Address  = &sound[1];
  829.       sound->AHISampleInfo.ahisi_Length = length;
  830.             
  831.       if(!AHI_LoadSound(sound->Sound, AHIST_SAMPLE, &sound->AHISampleInfo, audio->AHIAudioCtrl))
  832.       {
  833.         audio->NextSound++;
  834.         AddTail((struct List *) &audio->Sounds, (struct Node *) sound);
  835. #ifdef POWERUP
  836.         PPCCacheClearE(sound, sizeof(struct ASound), CACRF_ClearD);
  837. #endif
  838.         return(sound);
  839.       }
  840.       
  841.       memFree(sound);
  842.     }
  843.   }
  844.   else
  845.   {
  846.     if(res != 8)
  847.       return(NULL);
  848.  
  849.     step = AResample(&freq, MAX_PAULA_FREQUENCY, &length, MAX_PAULA_LENGTH);
  850.     
  851.     if(AvailMem(MEMF_CHIP|MEMF_PUBLIC) >= (audio->MinFreeChip + length))
  852.       buffer = AllocVec(length, MEMF_CHIP|MEMF_PUBLIC);
  853.     else
  854.       buffer = NULL;
  855.  
  856.     if(buffer)
  857.       sound = memAlloc(sizeof(struct ASound));
  858.     else
  859.     {
  860.       sound = memAlloc(sizeof(struct ASound) + length);
  861.       
  862.       if(sound)
  863.         buffer = (UBYTE *) &sound[1];
  864.     }
  865.     
  866.     if(sound)
  867.     {
  868.       sound->Sound            = audio->NextSound;
  869.       sound->Frequency          = freq;
  870.       sound->Volume           = vol;
  871.       sound->AHISampleInfo.ahisi_Address  = buffer;
  872.       sound->AHISampleInfo.ahisi_Length = length;
  873.         
  874.       if(step == 0x100)
  875.         memcpy(buffer, sample, length);
  876.       else
  877.       {
  878.         for(i = 0, j = 0; i < length; i++, j += step)
  879.           buffer[i] = sample[j >> 8];
  880.       }
  881.  
  882.       audio->NextSound++;
  883.       AddTail((struct List *) &audio->Sounds, (struct Node *) sound);
  884. #ifdef POWERUP
  885.       PPCCacheClearE(sound, sizeof(struct ASound), CACRF_ClearD);
  886. #endif
  887.       return(sound);
  888.     }
  889.     else if(buffer)
  890.       FreeVec(buffer);
  891.   }
  892.  
  893.   return(NULL);
  894. }
  895.  
  896. struct ASound *AReadSound(struct Audio *audio, BPTR file)
  897. {
  898.   struct MameSample mame_sample;
  899.   struct ASound   *sound;
  900.   UBYTE       *buffer;
  901.   UBYTE       *sample;
  902.   LONG        step;
  903.   LONG        i, j;
  904.   LONG        frequency;
  905.   LONG        length;
  906.   
  907.   if(Read(file, &mame_sample, sizeof(struct MameSample)) == sizeof(struct MameSample))
  908.   {
  909.     if((mame_sample.ID == MAKE_ID('M','A','M','E')) && mame_sample.Length)
  910.     {
  911.       frequency = INTELULONG(mame_sample.Frequency);
  912.       length    = INTELULONG(mame_sample.Length);
  913.       
  914.       if(audio->UseAHI)
  915.       {
  916.         sound = memAlloc(sizeof(struct ASound) + length);
  917.         
  918.         if(sound)
  919.         {
  920.           sound->Sound    = audio->NextSound;
  921.           sound->Frequency  = frequency;
  922.           sound->Volume   = mame_sample.Volume;
  923.           
  924.           Read(file, &sound[1], length);
  925.           
  926.           if((mame_sample.Resolution == 8) || (mame_sample.Resolution == 16))
  927.           {
  928.             if(mame_sample.Resolution == 8)
  929.               audio->AHISampleInfo.ahisi_Type = AHIST_M8S;
  930.             else
  931.               audio->AHISampleInfo.ahisi_Type = AHIST_M16S;
  932.           
  933.             sound->AHISampleInfo.ahisi_Address  = &sound[1];
  934.             sound->AHISampleInfo.ahisi_Length = length;
  935.             
  936.             if(!AHI_LoadSound(sound->Sound, AHIST_SAMPLE, &sound->AHISampleInfo, audio->AHIAudioCtrl))
  937.             {
  938.               audio->NextSound++;
  939.               AddTail((struct List *) &audio->Sounds, (struct Node *) sound);
  940. #ifdef POWERUP
  941.               PPCCacheClearE(sound, sizeof(struct ASound), CACRF_ClearD);
  942. #endif
  943.               return(sound);
  944.             }
  945.           }
  946.           
  947.           memFree(sound);
  948.         }
  949.       }
  950.       else
  951.       {
  952.         if(mame_sample.Resolution != 8)
  953.           return(NULL);
  954.  
  955.         step = AResample(&frequency, MAX_PAULA_FREQUENCY, &length, MAX_PAULA_LENGTH);
  956.     
  957.         if(AvailMem(MEMF_CHIP|MEMF_PUBLIC) >= (audio->MinFreeChip + length))
  958.           buffer = AllocVec(length, MEMF_CHIP|MEMF_PUBLIC);
  959.         else
  960.           buffer = NULL;
  961.  
  962.         if(buffer)
  963.           sound = memAlloc(sizeof(struct ASound));
  964.         else
  965.         {
  966.           sound = memAlloc(sizeof(struct ASound) + length);
  967.       
  968.           if(sound)
  969.             buffer = (UBYTE *) &sound[1];
  970.         }
  971.     
  972.         if(sound)
  973.         {
  974.           sound->Sound            = audio->NextSound;
  975.           sound->Frequency          = frequency;
  976.           sound->Volume           = mame_sample.Volume;
  977.           sound->AHISampleInfo.ahisi_Address  = buffer;
  978.           sound->AHISampleInfo.ahisi_Length = length;
  979.         
  980.           if(step == 0x100)
  981.             Read(file, buffer, length);
  982.           else
  983.           {
  984.             sample = AllocVec(INTELULONG(mame_sample.Length), MEMF_PUBLIC);
  985.             
  986.             if(sample)
  987.             {
  988.               Read(file, sample, INTELULONG(mame_sample.Length));
  989.               
  990.               for(i = 0, j = 0; i < length; i++, j += step)
  991.                 buffer[i] = sample[j >> 8];
  992.               
  993.               FreeVec(sample);
  994.             }
  995.             else
  996.             {
  997.               if(sound->AHISampleInfo.ahisi_Address != &sound[1])
  998.                 FreeVec(sound->AHISampleInfo.ahisi_Address);
  999.               
  1000.               memFree(sound);
  1001.               sound = NULL;
  1002.             }
  1003.           }
  1004.  
  1005.           if(sound)
  1006.           {
  1007.             audio->NextSound++;
  1008.             AddTail((struct List *) &audio->Sounds, (struct Node *) sound);
  1009. #ifdef POWERUP
  1010.             PPCCacheClearE(sound, sizeof(struct ASound), CACRF_ClearD);
  1011. #endif
  1012.             return(sound);
  1013.           }
  1014.         }
  1015.         else if(buffer)
  1016.           FreeVec(buffer);
  1017.       }
  1018.     }
  1019.   }
  1020.  
  1021.   return(NULL);
  1022. }
  1023.  
  1024. /****i* audio.c/AResample *************************************************
  1025. *
  1026. * NAME
  1027. *   AResample -- Calculate resample parameters.
  1028. *
  1029. * SYNOPSIS
  1030. *   step = AResample(frequency, maxfrequency, length, maxlength)
  1031. *
  1032. *   ULONG AResample(ULONG *, ULONG, ULONG *, ULONG);
  1033. *
  1034. * FUNCTION
  1035. *   Calculate resample parameters if the sample is too long or the
  1036. *   frequency too high.
  1037. *
  1038. * INPUTS
  1039. *   frequency    - A pointer to the frequency for the sample playback. The
  1040. *                  resampled playback frequency will be written back.
  1041. *   maxfrequency - Max frequency for a sample. Max frequency for the Amiga
  1042. *                  audio hardware is 28867.
  1043. *   length       - A pointer to the length of the sample. The resampled
  1044. *                  length will be written back.
  1045. *   maxlength    - Max length of sample. Max playback length for the
  1046. *                  Amiga audio hardware is 131072.
  1047. *     
  1048. * RESULT
  1049. *   step  - Fraction to add to the sample index to get to the next
  1050. *           sample that should be included in the resampled version.
  1051. *           The fraction is shifted up 8 bits so 0x100 means no
  1052. *           resampling needed.
  1053. *
  1054. * EXAMPLE
  1055. *
  1056. * NOTES
  1057. *
  1058. * BUGS
  1059. *
  1060. * SEE ALSO
  1061. *
  1062. **************************************************************************/
  1063.  
  1064. ULONG AResample(ULONG *freq, ULONG maxfreq, ULONG *length, ULONG maxlength)
  1065. {
  1066.   ULONG step;
  1067.  
  1068.   if(*freq > maxfreq)
  1069.   {
  1070.     step  = *length;
  1071.     *length = (*length * ((maxfreq << 8) / *freq)) >> 8;
  1072.     if(*length > maxlength)
  1073.       *length = maxlength;
  1074.     *freq = (*freq * ((*length<<8) / step))>>8;
  1075.     step  = (step<<8) / *length;
  1076.   }
  1077.   else
  1078.   {
  1079.     if(*length > maxlength)
  1080.     {
  1081.       *freq = (*freq * ((maxlength<<8) / *length))>>8;
  1082.       step  = (*length<<8) / maxlength;
  1083.       *length = maxlength;
  1084.     }
  1085.     else
  1086.       step = 1<<8;
  1087.   }
  1088.   *length = *length & 0xfffffffc;
  1089.   return(step);
  1090. }
  1091.